package com.joshua.spring.gateway.filter.router;

import com.google.common.net.HttpHeaders;
import com.joshua.spring.gateway.constant.SwaggerConstants;
import com.joshua.spring.gateway.entity.bo.RouteDefinitionGroup;
import com.joshua.spring.gateway.properties.SystemUniqueCodeHeaderValidProperties;
import com.joshua.spring.gateway.repo.RedisRouteDefinitionRepository;
import com.joshua.spring.util.JacksonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.config.GlobalCorsProperties;
import org.springframework.cloud.gateway.handler.FilteringWebHandler;
import org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;

import java.util.Calendar;

import static com.joshua.spring.constants.MicroServiceHttpHeaders.*;
import static com.joshua.spring.constants.MicroServiceHttpHeaders.UNKNOWN;

/**
 * projectName dragon-cloud
 * package com.joshua.spring.gateway.filter.router
 * classname  RoutePredicateHandlerMappingPlus
 * <p>
 * description 路由处理
 * </p>
 *
 * @author <a href="mailto:joshualwork@163.com">joshua_liu</a>
 * @date 2020/8/27 19:16
 */
@Slf4j
@Primary
@Component
public class RoutePredicateHandlerMappingPlus extends RoutePredicateHandlerMapping {
    @Autowired
    private RedisRouteDefinitionRepository redisRouteDefinitionRepository;

    @Autowired
    private SystemUniqueCodeHeaderValidProperties uniqueCodeHeaderValidProperties;

    public RoutePredicateHandlerMappingPlus(FilteringWebHandler webHandler, RouteLocator routeLocator, GlobalCorsProperties globalCorsProperties, Environment environment) {
        super(webHandler, routeLocator, globalCorsProperties, environment);
    }

    @Override
    protected void validateRoute(Route route, ServerWebExchange exchange) {
        RouteDefinitionGroup routeDefinitionGroup = redisRouteDefinitionRepository.ROUTE_DEFINITION_GROUP.get(route.getId());
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        org.springframework.http.HttpHeaders respHeaders = response.getHeaders();
        String path = request.getPath().toString();
        respHeaders.remove(X_APPLICATION);
        respHeaders.remove(X_CALL_TIME);
        respHeaders.set(X_INNER_SERVICE, route.getUri().toString());
        respHeaders.set(X_RPC_TIME, Calendar.getInstance().getTime().toString());
//        if (uniqueCodeHeaderValidProperties.isEnable()) {
//            String headerValue = request.getHeaders().getFirst(uniqueCodeHeaderValidProperties.getHeaderKey());
//            if (!uniqueCodeHeaderValidProperties.getHeaderValue().equalsIgnoreCase(headerValue)) {
//                log.error("System unique code valid fail");
//            }
//        }
        log.info("Start local route validate... \nRoute [{}],\nHttp request method [{}], uri [{}], client ip [{}]",
                JacksonUtils.obj2json(routeDefinitionGroup), request.getMethodValue(), request.getURI(), getIpAddress(request));
        if (path.contains(SwaggerConstants.DOCS_URI_WITH_PREFIX)) {
            request.mutate().header(X_REAL_SWAGGER_PATH, path).build();
        } else {

        }
        if (routeDefinitionGroup.isEnable()) {
//            if (ignorePaths.contains(path)) {
//                //直接放行
//            } else{
//                validateToke(request.getHeaders().getFirst("Auth"));
//            }
        } else {
            log.error("Route not exist or route had been disabled");
        }
    }

    private String getIpAddress(ServerHttpRequest request) {
        String ip = request.getHeaders().getFirst(HttpHeaders.X_FORWARDED_FOR);
        if (StringUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeaders().getFirst(PROXY_CLIENT_IP);
        }
        if (StringUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeaders().getFirst(WL_PROXY_CLIENT_IP);
        }
        if (StringUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeaders().getFirst(HTTP_CLIENT_IP);
        }
        if (StringUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeaders().getFirst(HTTP_X_FORWARDED_FOR);
        }
        if (StringUtils.isEmpty(ip) || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddress().getHostString();
        }
        return ip;
    }
}
